﻿using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using YlisChat.Models;

namespace YlisChat.Hubs
{
    public class ChatSubscriber
    {
        public static void SendMessage(Discussion msg)
        {
            if (msg.SystemMessage)
            {
                // If we got system message, try to find if the system message subject is our subscriber
                ChatSubscriber sub = default(ChatSubscriber);
                foreach (List<ChatSubscriber> item in ChatHub.ConnectedCache.Values)
                {
                    sub = item.Find(x => x.UserId == msg.UserId);
                    if (sub != default(ChatSubscriber))
                        break;
                }
                if (sub != default(ChatSubscriber))
                {
                    // If system message subject is our subscriber, add or remove the subscriber from Cache
                    if (!ChatHub.ConnectedCache.ContainsKey(msg.HashTag))
                        ChatHub.ConnectedCache[msg.HashTag] = new List<ChatSubscriber>();

                    if (msg.Message.Contains("joined") || msg.Message.Contains("created"))
                    {
                        ChatHub.ConnectedCache[msg.HashTag].Add(sub);
                    }
                    else
                    {
                        ChatHub.ConnectedCache[msg.HashTag].Remove(sub);
                    }
                }
            }

            if (!ChatHub.ConnectedCache.ContainsKey(msg.HashTag))
                return;

            IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
            if (hubContext != null)
            {

                List<string> ConnectionIds = ChatHub.ConnectedCache[msg.HashTag].ConvertAll(x => x.ConnectionId);
                hubContext.Clients.Clients(ConnectionIds).receive(msg);
            }
        }

        public string ConnectionId { get; set; }
        public string UserId { get; set; }
    }

    [Authorize]
    public class ChatHub : Hub
    {
        /// <summary>
        /// Dictionary key HashTah, List Userids
        /// </summary>
        public static Dictionary<string, List<ChatSubscriber>> ConnectedCache = new Dictionary<string, List<ChatSubscriber>>();

        public override Task OnConnected()
        {
            // Add your own code here.
            // For example: in a chat application, record the association between
            // the current connection ID and user name, and mark the user as online.
            // After the code in this method completes, the client is informed that
            // the connection is established; for example, in a JavaScript client,
            // the start().done callback is executed.
            ApplicationDbContext db = new ApplicationDbContext();
            ClaimsIdentity identity = Context.User.Identity as ClaimsIdentity;
            string userId = identity.GetUserId();
            List<UserList> userChannels = (from usrl in db.UserList
                                           where usrl.UserId == userId
                                           select usrl).ToList();

            ChatSubscriber subscriber = new ChatSubscriber()
            {
                UserId = userId,
                ConnectionId = Context.ConnectionId
            };

            foreach (UserList item in userChannels)
            {
                if (!ConnectedCache.ContainsKey(item.HashTag))
                    ConnectedCache[item.HashTag] = new List<ChatSubscriber>();

                ConnectedCache[item.HashTag].Add(subscriber);
            }

            return base.OnConnected();
        }

        public override Task OnDisconnected(bool stopCalled)
        {
            // Add your own code here.
            // For example: in a chat application, mark the user as offline, 
            // delete the association between the current connection id and user name.

            ApplicationDbContext db = new ApplicationDbContext();
            ClaimsIdentity identity = Context.User.Identity as ClaimsIdentity;
            string userId = identity.GetUserId();
            foreach (List<ChatSubscriber> item in ConnectedCache.Values)
            {
                int index = item.FindIndex(x => x.UserId == userId);
                if (index >= 0)
                    item.RemoveAt(index);
            }

            return base.OnDisconnected(stopCalled);
        }

        public override Task OnReconnected()
        {
            // Add your own code here.
            // For example: in a chat application, you might have marked the
            // user as offline after a period of inactivity; in that case 
            // mark the user as online again.
            return base.OnReconnected();
        }

        public void Send(Discussion message)
        {
            
        }
    }
}